package me.zhengjie.common.utils.CRC

object CRC_CCITT_1021 {
    /**
     * CRC-CCITT(Kermit)验证模式
     * @param str
     * @return
     */
    fun CRC_CCITT_Kermit(str: String): String {
        var j: Int
        val b: Int
        var rrrc: Int
        var c: Int
        var i: Int
        val tmpBalance: String
        var k: Int
        rrrc = 0
        tmpBalance = str
        var tmpInt: Int
        var CharInt: Int
        var tmpChar: String
        var tmpStr: String
        tmpStr = ""
        var High: Int
        var Low: Int
        j = 1
        while (j <= 3) {
            High = if (Character.isDigit(tmpBalance[2 * j - 2])) {
                (tmpBalance[2 * j - 2].toString() + "").toInt()
            } else {
                0
            }
            Low = if (Character.isDigit(tmpBalance[2 * j - 1])) {
                (tmpBalance[2 * j - 1].toString() + "").toInt()
            } else {
                0
            }
            High = High and 0xff shl 4
            High = High or Low
            k = High
            i = 1
            while (i <= 8) {
                c = rrrc and 1
                rrrc = rrrc shr 1
                if (k and 1 != 0) {
                    rrrc = rrrc or 0x8000
                }
                if (c != 0) {
                    rrrc = rrrc xor 0x8408
                }
                k = k shr 1
                i++
            }
            j++
        }
        i = 1
        while (i <= 16) {
            c = rrrc and 1
            rrrc = rrrc shr 1
            if (c != 0) {
                rrrc = rrrc xor 0x8408
            }
            i++
        }
        c = rrrc shr 8
        b = rrrc shl 8
        rrrc = c or b
        tmpInt = rrrc
        tmpStr = ""
        i = 1
        while (i <= 4) {
            tmpChar = ""
            CharInt = tmpInt % 16
            if (CharInt > 9) {
                when (CharInt) {
                    10 -> tmpChar = "A"
                    11 -> tmpChar = "B"
                    12 -> tmpChar = "C"
                    13 -> tmpChar = "D"
                    14 -> tmpChar = "E"
                    15 -> tmpChar = "F"
                }
            } else {
                tmpChar = Integer.toString(CharInt)
            }
            tmpInt = tmpInt / 16
            tmpStr = tmpChar + tmpStr
            i++
        }
        println("tmpStr:$tmpStr")
        return tmpStr
    }

    /**
     * CRC-CCITT(XModem)
     * CRC-CCITT(0xFFFF)
     * CRC-CCITT(0x1D0F)
     * 校验模式
     * @param flag< XModem(flag=1) 0xFFFF(flag=2) 0x1D0F(flag=3)>
     * @param str
     * @return
     */
    fun CRC_CCITT(flag: Int, str: String): String {
        var str = str
        var crc = 0x00 // initial value
        val polynomial = 0x1021
        val bytes = str.toByteArray()
        when (flag) {
            1 -> crc = 0x00
            2 -> crc = 0xFFFF
            3 -> crc = 0x1D0F
        }
        for (index in bytes.indices) {
            val b = bytes[index]
            for (i in 0..7) {
                val bit = b.toInt() shr 7 - i and 1 == 1
                val c15 = crc shr 15 and 1 == 1
                crc = crc shl 1
                if (c15 xor bit) crc = crc xor polynomial
            }
        }
        crc = crc and 0xffff
        str = Integer.toHexString(crc)
        return str
    }
}